﻿using log4net.Appender;
using log4net.Core;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace HobSoft.SoccerBet2014.Client.Log
{
    public class ApplicationCacheLogAppender : AppenderSkeleton
    {
        public static void Register()
        {
            Singleton = new ApplicationCacheLogAppender();
            log4net.Config.BasicConfigurator.Configure(Singleton);
            var logRepository = log4net.LogManager.GetRepository() as log4net.Repository.Hierarchy.Hierarchy;
            logRepository.Root.AddAppender(Singleton);
            logRepository.Root.Level = log4net.Core.Level.All;
            logRepository.Configured = true;
            logRepository.Name = "ApplicationCacheLog";
            logRepository.RaiseConfigurationChanged(EventArgs.Empty);
            
        }

        public static ApplicationCacheLogAppender Singleton
        {
            get;
            protected set;
        }

        public ApplicationCacheLogAppender()
        {
            bindCacheList = new List<LogCacheCollection>();
        }

        private IList<LogCacheCollection> bindCacheList;
        protected override void Append(LoggingEvent loggingEvent)
        {
            foreach (var cacheList in bindCacheList)
            {
                while (cacheList.Collection.Count > cacheList.MaxQueueCount)
                {
                    lock (cacheList.SyncRoot)
                    {
                        if (cacheList.Collection.Count > cacheList.MaxQueueCount)
                        {
                            var last = cacheList.Collection.LastOrDefault();
                            if (last != null) cacheList.Collection.Remove(last);
                        }
                    }
                }

                if (cacheList.AddCheck == null || cacheList.AddCheck(loggingEvent))
                {
                    cacheList.Collection.Insert(0, loggingEvent);
                }
            }
        }

        public void AddCacheCollection(ObservableCollection<LoggingEvent> bindCollection, uint bindMaxCount, Func<LoggingEvent, bool> bindCheck)
        {
            if (bindCollection == null)
                throw new ArgumentNullException("bindCollection", "need bindCollection");
            if (bindMaxCount < 1)
                throw new ArgumentException("bindMaxCount 至少大于0", "bindMaxCount");

            if (bindCacheList.Any(bl => bl.Collection.Equals(bindCollection)))
                return;
            bindCacheList.Add(new LogCacheCollection(bindCollection, bindMaxCount, bindCheck));
        }

    }
}
